package com.guoguo.cloudmusic.logic.network

import android.util.Log
import  com.guoguo.cloudmusic.logic.network.api.UserService
import com.guoguo.cloudmusic.ui.login.LoginUser
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.await
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

/**
 * PlaceNetwork 单例类
 * 定义一个统一的网络数据源访问入口，对所有网络请求的API进行封装
 * @author GuoGuo
 * @date 2021/12/15
 */
object ApplicationNetWork {
    /**
     * 如果你并不熟悉什么是动态代理也没有关系
     * 你只需要知道有了动态代理对象之后，我们就可以随意调用接口中定义的所有方法，
     * 而Retrofit会自动执行具体的处理就可以了
     */

    //  使用ServiceCreator创建一个UserService接口的动态代理对象   然后定义挂起函数
    //  private val placeService = ServiceCreator.create<com.example.naturehero.logic.network.api.PlaceService>()
    private val UserService = ServiceCreator.create(UserService::class.java)
    suspend fun login(data: LoginUser) = UserService.login(data.userName, data.md5_password).await()
    suspend fun search(data: String) = UserService.search(data).await()
    suspend fun getPlayList(data: String) = UserService.getPlayList(data).await()
    suspend fun getPlayListTrack(data: String) = UserService.getPlayListTrack(data, 100).await()
    suspend fun getRecommendSongs() = UserService.getRecommendSongs().await()
    suspend fun getLyric(id: Int) = UserService.getLyric(id).await()
    suspend fun getMusicUrl(id: String) = UserService.getMusicUrl(id).await()
    suspend fun getMusicComment(id: String) = UserService.getComment(id).await()
    suspend fun getTopList() = UserService.getTopList().await()
    /*
    * 当调用了AppService的getAppData()方法时，会返回一个Call<T>>对象，这时我们再调用一下它的enqueue()方法，
    * Retrofit就会根据注解中配置的服务器接口地址去进行网络请求了，服务器响应的数据会回调到enqueue()方法中传入的Callback实现里面。
    * 需要注意的是，当发起请求的时候，Retrofit会自动在内部开启子线程，当数据回调到Callback中之后，Retrofit又会自动切换回主线程，
    * 整个操作过程中我们都不用考虑线程切换问题。在Callback的onResponse()方法中，调用response.body()方法将会得到Retrofit解析后的对象，
    * 也就是Call<T>>中 T类型的数据
    */

    private suspend fun <T> Call<T>.await(): T {
        return suspendCoroutine {
            enqueue(object : Callback<T> {
                override fun onResponse(call: Call<T>, response: Response<T>) {
                    val body = response.body()
                    Log.d("response", body.toString())
//                    val requestStatus = Gson().fromJson(Gson().toJson(body).toString(), RequestModel::class.java)
                    if (body !== null) it.resume(body)
                    else it.resumeWithException(RuntimeException("response body is null"))
                }

                override fun onFailure(call: Call<T>, t: Throwable) {
                    it.resumeWithException(t)
                }
            })
        }
    }
}